package com.xbongbong.paas.controller.dingtalk;

import com.alibaba.dingtalk.openapi.exception.OApiException;
import com.alibaba.dingtalk.openapi.helper.AuthHelper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.manager.DingtalkManager;
import com.xbongbong.paas.pojo.dto.DingtalkConfigGetDTO;
import com.xbongbong.paas.pojo.vo.DingtalkConfigGetVO;
import com.xbongbong.paas.service.SnsLoginService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.URLEncodeUtils;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.dingtalk.pojo.dto.CoolAppAccessStatusDTO;
import com.xbongbong.pro.dingtalk.pojo.dto.DingtalkBeforeConfigDTO;
import com.xbongbong.pro.dingtalk.pojo.dto.DingtalkLoginInfoDTO;
import com.xbongbong.pro.dingtalk.pojo.dto.GenerateNonceDTO;
import com.xbongbong.pro.dingtalk.pojo.dto.RefreshAccessTokenDTO;
import com.xbongbong.pro.dingtalk.pojo.dto.SnsUserInfoDTO;
import com.xbongbong.pro.dingtalk.pojo.vo.CoolAppAccessStatusVO;
import com.xbongbong.pro.dingtalk.pojo.vo.DingtalkBeforeConfigVO;
import com.xbongbong.pro.dingtalk.pojo.vo.DingtalkLoginInfoVO;
import com.xbongbong.pro.dingtalk.pojo.vo.GenerateNonceVO;
import com.xbongbong.pro.dingtalk.pojo.vo.GetFrontUrlVO;
import com.xbongbong.pro.dingtalk.pojo.vo.ScanLoginVO;
import com.xbongbong.pro.dingtalk.pojo.vo.SnsUserInfoVO;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Objects;

/**
 * 用以处理一些与钉钉交互相关的接口
 * @author kaka
 * @time 2018-10-16 19:39
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/dingtalk")
public class DingtalkController {

    private static final Logger LOG = LoggerFactory.getLogger(DingtalkController.class);

    @Resource
    private SnsLoginService snsLoginService;
    @Resource
    private DingtalkManager dingtalkManager;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private AuthHelper authHelper;

    /**
     * 获取链接对应的签名
     * @param configGetDTO 关联DTO
     */
    @RequestMapping(value = "/auth/config", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String config(@RequestBody @Valid DingtalkConfigGetDTO configGetDTO, BindingResult br, HttpServletRequest request) throws Exception {
        XbbResponse<DingtalkConfigGetVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                DingtalkConfigGetVO configGetVO = dingtalkManager.getConfig(request, configGetDTO);
                response = new XbbResponse<>(configGetVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 强制刷新corpid对应公司的accessToken
     */
    @RequestMapping(value = "/refreshAccessToken", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String refreshAccessToken(@RequestBody @Valid RefreshAccessTokenDTO refreshTokenDTO, BindingResult br) throws Exception {
        XbbResponse<BaseVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                authHelper.getAccessToken(refreshTokenDTO.getCorpid(), true);
                response = new XbbResponse<>(new BaseVO());
            } catch (OApiException e) {
                LOG.warn("refreshAccessToken error", e);
                XbbException xe = new XbbException(SystemErrorCodeEnum.API_ERROR_100001, e.getErrMsg());
                response = new XbbResponse<>(xe);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 钉钉登录动作，通过corpid,code获取当前登录的人员信息，主要是userId
     * 1. 钉钉手机端微应用/E应用登录 dingtalk
     * 2. 钉钉PC客户端微应用登录 dingtalkPc
     * 3. 钉钉管理后台微应用登录 dingtalkAdmin
     */
    @RequestMapping(value = "/loginInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String loginInfo(@RequestBody @Valid DingtalkLoginInfoDTO loginInfoDTO, BindingResult br, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws Exception {
        XbbResponse<DingtalkLoginInfoVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                DingtalkLoginInfoVO loginInfoVO = dingtalkManager.loginInfo(httpRequest, httpResponse, loginInfoDTO);
                response = new XbbResponse<>(loginInfoVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }
    
    @RequestMapping(value = "/beforeConfig", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String beforeConfig(@RequestBody @Valid DingtalkBeforeConfigDTO dingtalkBeforeConfigDTO, BindingResult br, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws Exception {
        XbbResponse<DingtalkBeforeConfigVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                DingtalkBeforeConfigVO dingtalkBeforeConfigVO = dingtalkManager.beforeConfig(dingtalkBeforeConfigDTO);
                response = new XbbResponse<>(dingtalkBeforeConfigVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/pc/generateNonce", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String generateNonce(@RequestBody @Valid GenerateNonceDTO generateNonceDTO, BindingResult br) throws Exception {
        XbbResponse<GenerateNonceVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                GenerateNonceVO generateNonceVO = dingtalkManager.generateNonce(generateNonceDTO);
                response = new XbbResponse<>(generateNonceVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 获取dingtalk/web前端服务地址
     */
    @RequestMapping(value = "/getFrontUrl", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String getFrontUrl(@RequestBody JSONObject jsonObject, BindingResult br) throws Exception {
        XbbResponse<GetFrontUrlVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            GetFrontUrlVO frontUrlVO = new GetFrontUrlVO();
            frontUrlVO.setDingtalkFrontUrl(ProBaseConfig.getDingtalkFrontUrl());
            frontUrlVO.setWebFrontUrl(proBaseConfig.getWebFrontUrl());
            response = new XbbResponse<>(frontUrlVO);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 获取pro扫码登录gotoUrl
     */
    @RequestMapping(value = "/sns/scanLogin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String scanLogin(@RequestBody JSONObject jsonObject, BindingResult br) throws Exception {
        XbbResponse<ScanLoginVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            ScanLoginVO scanLoginVO = new ScanLoginVO();
            String scanCodeUrl;
            if ("xbbProDev".equals(ProBaseConfig.getProjectName()) || "xbbProOmsDev".equals(ProBaseConfig.getProjectName())) {
                scanCodeUrl = "scan-code.html";
            } else {
                scanCodeUrl = "pro/scan-code.html";
            }
            String gotoUrl = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="
                    + proBaseConfig.getScanAppId()
                    + "&response_type=code&scope=snsapi_login&state=STATE&redirect_uri="
                    + ProBaseConfig.getDingtalkFrontUrl()
                    + scanCodeUrl;
            scanLoginVO.setGotoUrl(gotoUrl);
            scanLoginVO.setGotoUrlEncode(URLEncodeUtils.encodeURL(gotoUrl));
            response = new XbbResponse<>(scanLoginVO);
        }
        return JSON.toJSONString(response);
    }


    /**
     * 扫码登录获取登录用户信息
     */
    @RequestMapping(value = "/sns/userInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String userInfo(@RequestBody @Valid SnsUserInfoDTO snsUserInfoDTO, BindingResult br) throws Exception {
        XbbResponse<SnsUserInfoVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                SnsUserInfoVO snsUserInfoVO = snsLoginService.snsUserInfo(snsUserInfoDTO.getCode());
                response = new XbbResponse<>(snsUserInfoVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }

        return JSON.toJSONString(response);
    }

    /**
     * 应用市场：酷应用访问状态
     */
    @RequestMapping(value = "/appMarket/coolApps/status", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String coolAppStatus(@RequestBody @Valid CoolAppAccessStatusDTO coolAppStatusDTO) {
        LOG.info("*********source:{},---qunId:{}, corpid:{}, authCode:{}, coolAppCode:{}",coolAppStatusDTO.getSource(),coolAppStatusDTO.getEncFieldBizCode(),coolAppStatusDTO.getCorpid()
                ,coolAppStatusDTO.getAuthCode(), coolAppStatusDTO.getCoolAppCode());
        CoolAppAccessStatusVO statusVO = dingtalkManager.getCoolAppAccessStatus(coolAppStatusDTO);
        // 拿到返回值原封不动地调用在回调方法回传
        // data的格式需要是这样：{status: 'xxxx'}
        return JSON.toJSONString(statusVO);
    }

}
